package spring.jpa.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.web.bind.annotation.ControllerAdvice;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

// 开启 SpringDataJPA https://www.jianshu.com/p/23c1354bb045
@EnableJpaRepositories(basePackages = "spring.jpa.repository.springdata")
// @EnableTransactionManagement
// 加载 properties 文件
@PropertySource("classpath:db.properties")
// 扫描包路径，spring 扫描除 controller 层以外的，spring 不可从子容器(spring mvc)中获取 bean
@ComponentScan(basePackages = {"spring.jpa"}, excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, ControllerAdvice.class})
})
public class RootConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        // entityManagerFactoryBean.setPersistenceUnitName("jpaname");

        entityManagerFactoryBean.setDataSource(dataSource);

        // jpa 提供商的适配器
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);
        entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);

        // jpa 注解所在的包
        entityManagerFactoryBean.setPackagesToScan("spring.jpa.entity");

        Map<String, Object> map = new HashMap<>();
        map.put("hibernate.show_sql", true);
        map.put("hibernate.format_sql", true);
        map.put("hibernate.hbm2ddl.auto", "update");
        map.put("hibernate.cache.use_second_level_cache", true);
        map.put("hibernate.cache.region.factory_class", "org.hibernate.cache.jcache.internal.JCacheRegionFactory");
        map.put("hibernate.cache.use_query_cache", true);
        entityManagerFactoryBean.setJpaPropertyMap(map);

        return entityManagerFactoryBean;
    }

    /**
     * Druid 数据源
     */
    @Bean
    public DataSource dataSource(@Value("${db.username}") String name, @Value("${db.password}") String password,
                                 @Value("${db.url}") String url, @Value("${db.driver}") String driver) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(name);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driver);
        return dataSource;
    }

    // @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}